﻿using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Dora.Tools.Utility
{
    public static class SerializerExtentions
    {
        #region .Net JsonSerializer
        /// <summary>
        /// 序列化对象成Json字符串, 生成短时间格式
        /// </summary>
        /// <typeparam name="T">待序列化的类型</typeparam>
        /// <param name="t">该类型的参数</param>
        /// <returns></returns>
        //public static string ToJson<T>(this T t)
        //{
        // var setting = new DataContractJsonSerializerSettings();
        // setting.DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat("yyyy-MM-dd hh:mm:ss");
        // DataContractJsonSerializer serialzer = new DataContractJsonSerializer(typeof(T), setting);
        // string json;
        // using (var stream = new MemoryStream())
        // {
        // serialzer.WriteObject(stream, t);
        // json = Encoding.UTF8.GetString(stream.ToArray());
        // }
        // return json;
        //}
        #endregion
        /// <summary>
        /// 序列化对象成Json字符串. 日期时间格式： "yyyy'-'MM'-'dd' 'HH':'mm':'ss"
        /// </summary>
        /// <param name="t">待序列的对象</param>
        /// <param name="T">待序列对象类型</param>
        /// <returns></returns>
        public static string SerializeToJson<T>(this T t) where T : class
        {
            try
            {
                IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
                //这里使用自定义日期格式，如果不使用的话，默认是ISO8601格式 
                timeConverter.DateTimeFormat = "yyyy'-'MM'-'dd' 'HH':'mm':'ss";
                return JsonConvert.SerializeObject(t, timeConverter);
            }
            catch (JsonSerializationException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 序列化对象到文件. 日期时间格式： "yyyy'-'MM'-'dd' 'HH':'mm':'ss"
        /// </summary>
        /// <param name="t">待序列的对象</param>
        /// <param name="T">待序列对象类型</param>
        /// <param name="filename">目标文件路径，指定的文件不存在则创建，否则添加文本</param>
        public static void SerializeToJson<T>(this T t, string filename) where T : class
        {
            var json = t.SerializeToJson();
            using (var sw = File.CreateText(filename))
            {
                sw.Write(json);
            }
        }

        /// <summary>
        /// 从Json字符串反序列化对象
        /// </summary>
        /// <param name="str">Json字符串或文件名</param>
        /// <param name="T">反序列化的目标类型</param>
        /// <param name="isFile">指示str是否是文件</param>
        /// <returns></returns>
        public static T DesializeJsonToObject<T>(this string str, bool isFile) where T : class
        {
            string json;
            if (isFile)
            {
                if (!File.Exists(str))
                    throw new FileNotFoundException(string.Format("{0} 位置未发现文件！", str));
                json = File.ReadAllText(str);
            }
            else
                json = str;
            try
            {
                return JsonConvert.DeserializeObject<T>(json);
            }
            catch (JsonSerializationException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 序列化对象成xml
        /// </summary>
        /// <param name="t">待序列化的对象</param>
        /// <param name="T">待序列化对象的类型</param>
        /// <returns></returns>
        public static string SerializeToXml<T>(this T t) where T : class
        {
            var sw = new StringWriter();
            XmlSerializer serializer = new XmlSerializer(t.GetType());
            try
            {
                serializer.Serialize(sw, t);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return sw.ToString();
        }

        /// <summary>
        /// 序列化对象成文件
        /// </summary>
        /// <typeparam name="T">待序列化对象的类型</typeparam>
        /// <param name="t">待序列化的对象</param>
        /// <param name="filename"></param>
        public static void SerializeToXml<T>(this T t, string filename) where T : class
        {
            XmlSerializer serializer = new XmlSerializer(t.GetType());
            try
            {
                using (FileStream fs = new FileStream(filename, FileMode.Create))
                {
                    serializer.Serialize(fs, t);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 反序列化xml为对象
        /// </summary>
        /// <typeparam name="T">目标对象类型</typeparam>
        /// <param name="str">xml字符串或文件</param>
        /// <param name="isFile">指示str是否是文件</param>
        /// <returns></returns>
        public static T DeserializeXmlToObject<T>(this string str, bool isFile) where T : class
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            if (isFile)
            {
                if (!File.Exists(str))
                    throw new FileNotFoundException(string.Format("{0} 位置未发现文件"));
                using (var reader = XmlReader.Create(str))
                {
                    return (T)serializer.Deserialize(reader);
                }
            }
            else
            {
                using (var reader = new StringReader(str))
                {
                    return (T)serializer.Deserialize(reader);
                }
            }
        }


        #region object转T
        /// <summary>
        ///  赵刚
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T Cast<T>(this object obj)
        {
            if (obj == null) return default(T);
            if (obj is T) return (T)obj;
            //var unixtime = new UnixDateTimeConverter();
            //var jsonStr = JsonConvert.SerializeObject(obj, unixtime);
            var jsonStr = JsonConvert.SerializeObject(obj);
            if (string.IsNullOrEmpty(jsonStr)) return default(T);
            try
            {
                T value = JsonConvert.DeserializeObject<T>(jsonStr);
                return value;
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        #endregion
    }
}